//
// Created by shen on 2025/2/27.
//

#include "AVFrameQueue.h"
#include "SLog.h"

AVFrameQueue::AVFrameQueue(FFStatus *ffStatus) : ffStatus(ffStatus) {}

AVFrameQueue::~AVFrameQueue() = default;

int AVFrameQueue::putAvFrame(AVFrame *avFrame) {
    std::unique_lock<std::mutex> lock(mutex);
    queuePacket.push(avFrame);
    cond.notify_all();
    return 0;
}
int AVFrameQueue::putStructAvFrame(frameStruct *structFrame) {
    std::unique_lock<std::mutex> lock(mutex);

    structQueuePacket.push(structFrame);
    //LOGE("向列队插入一个packet 当前总共 %d 个",queuePacket.size());
    cond.notify_all();
    return 0;
}

int
AVFrameQueue::getStructAvFrame(frameStruct **structFrame, double timestamp, AVRational bastTime) {
    std::unique_lock<std::mutex> lock(mutex);
    while (ffStatus!= nullptr&&ffStatus->exit){
        if (structQueuePacket.size()>0){
            frameStruct * frame = structQueuePacket.front();
            double pts = frame->pts;
            if (timestamp >= (pts - 0.03)){
                *structFrame = frame;
                structQueuePacket.pop();
            }
            SLog::GetInstance().get()->getLogger().get()->info("\"取出一个packet  当前剩余 %d 个\",queuePacket.size()");
            break;
        }else{
            cond.notify_all();
        }
    }
    return 0;
}
void AVFrameQueue::noticeQueue() {
    cond.notify_all();
}
void AVFrameQueue::clearAvPacket() {
     cond.notify_all();
    std::unique_lock<std::mutex> lock(mutex);
    while (!queuePacket.empty()){
        auto *avFrame=queuePacket.front();
        queuePacket.pop();

        av_frame_free(&avFrame);
        av_free(avFrame);
        avFrame = nullptr;
    }
    while (!structQueuePacket.empty()){
        frameStruct * avFrame = structQueuePacket.front();
        structQueuePacket.pop();
        avFrame = nullptr;
    }
}
int AVFrameQueue::getQueueSize() {
    std::unique_lock<std::mutex> lock(mutex);
    int size = queuePacket.size() + structQueuePacket.size();
    return 0;
}


int AVFrameQueue::getAvFrameByTime(AVFrame *avFrame, double timestamp, AVRational bastTime) {
    std::unique_lock<std::mutex> lock(mutex);

    while(ffStatus!= nullptr&&ffStatus->exit){
        auto *frame=queuePacket.front();
        int ret= av_frame_ref(avFrame,frame);
        double pts=avFrame->pts;
        pts *= av_q2d(bastTime);

        if (ret==0&&timestamp>=(pts-0.03)){
            queuePacket.pop();

            av_frame_free(&frame);
            av_free(frame);
            frame = nullptr;
        }else if (frame->data[0]!= nullptr&&timestamp>=(pts-0.03)){
            queuePacket.pop();

            av_frame_free(&frame);
            av_free(frame);
            frame = nullptr;
        }else{
            cond.wait(lock);
        }
    }
    return 0;
}


int AVFrameQueue::getAvFrame(AVFrame *avFrame) {

    std::unique_lock<std::mutex> lock(mutex);
    LOGCATE("size = %d ",queuePacket.size());
    while(ffStatus!= nullptr&&!ffStatus->exit){
        if (!queuePacket.empty()){
            AVFrame * avFrame1 = queuePacket.front();
            int ret = av_frame_ref(avFrame,avFrame1);
            avFrame->linesize[0] = avFrame1->linesize[0];
            if (ret == 0){
                queuePacket.pop();
            }
            av_frame_free(&avFrame1);
            av_free(avFrame1);
            avFrame1 = NULL;
            break;
        }else{
            cond.wait(lock);
        }
    }
    return 0;
}
